/*
 * Copyright (c) 2011 Obix Labs Limited
 * Redistribution and use in source and binary forms, 
 * with or without modification, are permitted provided 
 * that the following conditions are met:
 * 
 * 		Redistribution of source code must retain the above 
 * 		copyright notice, this list of conditions and the 
 * 		following disclaimer.
 *
 * 		Redistribution in binary form must reproduce the 
 * 		above copyright notice, this list of conditions 
 * 		and the following disclaimer in the documentation 
 * 		and/or other materials provided with the distribution.
 * 
 * 	THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF 
 * 	ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS 
 * 	AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
 * 	FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, 
 * 	ARE HEREBY EXCLUDED. OBIX LABS LIMITED ("Obix Labs") AND ITS 
 * 	LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE 
 * 	AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR 
 * 	ITS DERIVATIVES. IN NO EVENT WILL Obix Labs OR ITS LICENSORS BE 
 * 	LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, 
 * 	INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE 
 * 	DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF 
 * 	LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS 
 * 	SOFTWARE, EVEN IF Obix Labs HAS BEEN ADVISED OF THE POSSIBILITY OF 
 * 	SUCH DAMAGES.
 */
package com.obixlabs.commons.zip;

import java.io.Serializable;

import com.obixlabs.commons.util.SimpleHashCodeCalculator;

/**
 * <p>
 * Represents an item extracted from a compressed archive, 
 * for example a ZIP file. Subclasses of this type can be used
 * to represent {@link CompressedData files} and 
 * {@link CompressedDataFolder folders}. 
 * </p>
 */
public abstract class CompressedItem implements Serializable
{
	private static final long serialVersionUID = 545341589743947974L;
	
	/**
	 * <p>
	 * The name of the item.
	 * </p>
	 */
	private String name;
	
	/**
	 * <p>
	 * The item's parent. This would typically be a 
	 * {@link CompressedDataFolder directory/folder}.
	 * </p>
	 */
	private CompressedDataFolder parent;
	
	/**
	 * <p>
	 * Creates an instance with the given name.
	 * </p>
	 *  
	 * @param name	The name of the item.
	 */
	public CompressedItem(String name) 
	{this.name = name;}

	/**
	 * <p>
	 * Returns the item's {@link #name name/identifier}.
	 * </p>
	 * 
	 * @return	The item's name.
	 */
	public String getName() {return name;}

	
	/**
	 * <p>
	 * Returns the item's unqualified name. The 
	 * unqualified name is the name of the item 
	 * excluding the names of any parent folders 
	 * and path separators.  
	 * </p>
	 * 
	 * @return	The unqualified name of the item.
	 */
	public String getUnqualifiedName()
	{
		String result = name;
		
		if (result.endsWith(ZIPBuilder.ZIP_ENTRY_PATH_SEPERATOR))
			result = result.substring(0, result.length()-1);
		
		int seperatorIndex = 
				result.indexOf(
						ZIPBuilder.ZIP_ENTRY_PATH_SEPERATOR); 
		if (seperatorIndex>=0)
		{
			seperatorIndex = 
				result.lastIndexOf(
							ZIPBuilder.ZIP_ENTRY_PATH_SEPERATOR);			
			if (seperatorIndex+1<result.length())
				result  = result.substring(seperatorIndex+1);
			else result = "";
		}		
		return result;
	}	
	
	/**
	 * <p>
	 * Returns the item's {@link CompressedDataFolder
	 * parent}. 
	 * </p>
	 * 
	 * @return	The item's parent.	
	 */
	public CompressedDataFolder getParent() {return parent;}

	@Override
	public int hashCode()
	{ return SimpleHashCodeCalculator.calculateFromFields(name); }

	@Override
	public boolean equals(Object object)
	{
		boolean result = false;
		
		if (this == object) result=true;
		else if (object instanceof CompressedItem) 
		{
			CompressedItem other = (CompressedItem) object;
			if (name.equals(other.name)) result = true;
		}
		
		return result;
	}

	/**
	 * <p>
	 * Sets the {@link #parent item's parent}. This method 
	 * would typically be called when 
	 * {@link CompressedDataFolder#add(CompressedItem) 
	 * the item is added to a folder}.
	 * </p>
	 * 
	 * @param parent	The item's parent.
	 */
	protected void setParent(CompressedDataFolder parent)
	{ this.parent = parent; }
	
	/**
	 * <p>
	 * Determines if the given item is a {@link CompressedDataFolder folder type}.
	 * Put differently, it determines if the item is of type 
	 * {@link CompressedDataFolder}.
	 * </p>
	 * 
	 * @param item	The item to test.
	 * 
	 * @return	<code>True</code> if the given item is 
	 * of type {@link CompressedDataFolder}. 
	 */
	public static boolean isFolder(CompressedItem item)
	{ 
		return CompressedDataFolder.class.
										isAssignableFrom(
												item.getClass());
	}

}
